package com.zlt.bkparking.controller.salesman;


import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zlt.bkparking.entity.AdvertisementPlayed;
import com.zlt.bkparking.service.AdvertisementPlayedService;
import com.zlt.bkparking.service.AdvertisingEquipmentService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Date: 2022/10/11 15:56
 * @Author: hzj
 * @Description:
 */

@ServerEndpoint("/video/{id}")//userId：地址的111就是这个userId"ws://localhost:8181/wsserver/111"
@Component
public class WebSocketServer {


    /**用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;
    /**concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。*/
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话，需要通过它来给客户端发送数据*/
    private Session session;
    /**接收id*/
    private String id="";


    public static RedisTemplate redisTemplate ;


    public static   AdvertisingEquipmentService advertisingEquipmentService ;


    public static AdvertisementPlayedService advertisementPlayedService;

    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session,@PathParam("id") String id) {
        this.session = session;
        this.id=id;
        if(webSocketMap.containsKey(id)){
            webSocketMap.remove(id);
            webSocketMap.put(id,this);
            //加入set中
        }else{
            webSocketMap.put(id,this);
            //加入set中
            addOnlineCount();
            //设备数加1
        }
        System.out.println("设备连接:"+id+",当前在线设备为:" + getOnlineCount());
        try {
            //设备刚刚上线时，获取播放地址
            //是否存在播放列表

            List<Long> videos = advertisingEquipmentService.getAdvertisementByEquipmentId(Integer.valueOf(id));
            Long adId = getNum(videos);
            String url = null;
            if(Objects.isNull(adId)){
                url = "http://rjf0krhpu.hn-bkt.clouddn.com/376d7ca5-2f93-4755-95fc-c80a4a7291d3.mp4";
            }
            url = (String)redisTemplate.opsForValue().get("advertisement:id:" + adId);
            redisTemplate.opsForValue().decrement("advertisement:num:" + adId,1);
            HashMap<String, String> map = new HashMap<>();
            map.put("adId",adId.toString());
            map.put("url",url);
            String s = JSON.toJSONString(map);

            sendMessage(s);
        } catch (IOException e) {
            System.out.println("设备:"+id+",网络异常!!!!!!");
        }
    }




    public Long getNum(List<Long> videos ){
        Long adId = null;
        if (videos.size() == 1){
            adId = videos.get(0);
        }else {
            int i = new Random().nextInt(videos.size());
            adId = videos.get(i);
        }
        System.out.println("adId:"+adId);
        Integer num = (Integer) redisTemplate.opsForValue().get("advertisement:num:" + adId);
        if(!Objects.isNull(num) && num >= 0){
            return adId;
        }
        videos.remove(adId);
        return getNum(videos);
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(id)){
            webSocketMap.remove(id);
            //从set中删除
            subOnlineCount();
        }
        System.out.println("设备下线:"+id+",当前在线设备数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("设备消息:"+id+",报文:"+message);
        //得到广告id

        //可以群发消息
        //消息保存到数据库、redis
        if(StringUtils.isNotBlank(message)){
            try {
                //解析发送的报文
                JSONObject jsonObject = JSON.parseObject(message);
                String toId=jsonObject.getString("toId");
                String adIdMsg=jsonObject.getString("adId");
                String apStart=jsonObject.getString("apStart");
                String apEnd=jsonObject.getString("apEnd");
                AdvertisementPlayed advertisementPlayed = new AdvertisementPlayed();
                advertisementPlayed.setAdId(Long.valueOf(adIdMsg));
                advertisementPlayed.setApEnd(new Date(apEnd));
                advertisementPlayed.setApStart(new Date(apStart));
                advertisementPlayed.seteId(Integer.valueOf(toId));
                advertisementPlayedService.save(advertisementPlayed);


                List<Long> videos = advertisingEquipmentService.getAdvertisementByEquipmentId(Integer.valueOf(toId));
                Long adId = getNum(videos);
                String url = null;
                if(Objects.isNull(adId)){
                    url = "http://rjf0krhpu.hn-bkt.clouddn.com/376d7ca5-2f93-4755-95fc-c80a4a7291d3.mp4";
                }
                url = (String)redisTemplate.opsForValue().get("advertisement:id:" + adId);
                redisTemplate.opsForValue().decrement("advertisement:num:" + adId,1);
                HashMap<String, String> map = new HashMap<>();
                map.put("adId",adId.toString());
                map.put("url",url);
                String msg = JSON.toJSONString(map);
                //传送给对应toId用户的websocket
                if(StringUtils.isNotBlank(toId)&&webSocketMap.containsKey(toId)){
                    webSocketMap.get(toId).sendMessage(msg);
                }else{
                    System.out.println("请求的设备Id:"+toId+"不在该服务器上");
                    //否则不在这个服务器上，发送到mysql或者redis
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("设备错误:"+this.id+",原因:"+error.getMessage());
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);

    }


    /**
     * 发送自定义消息
     * */
    public static void sendInfo(String message,@PathParam("id") String id) throws IOException {
        System.out.println("发送消息到:"+id+"，报文:"+message);
        if(StringUtils.isNotBlank(id)&&webSocketMap.containsKey(id)){
            webSocketMap.get(id).sendMessage(message);
        }else{
            System.out.println("设备"+id+",不在线！");
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

}
